package edu.csu.smartpark.config;

import edu.csu.smartpark.filter.JwtFilter;
import edu.csu.smartpark.filter.MyAnonymousFilter;
import edu.csu.smartpark.shiro.*;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SubjectFactory;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.*;

@Configuration
/*
* @Description: shrio框架配置类
* @Author: LZY
* @Date: 2021/4/13 19:46
*/
public class ShiroConfig {

    @Bean
    public JwtRealm getJwtRealm(){
        return new JwtRealm();
    }


    @Bean
    /*
    * @Description: 配置shiro不要使用DefaultSubject创建对象，因为需要创建Session
    * @Author: LZY
    * @Date: 2021/4/19 22:18
    * @Params: []
    * @Return: org.apache.shiro.mgt.SubjectFactory
    */
    public SubjectFactory subjectFactory() {
        return new JwtDefaultSubjectFactory();
    }

    @Bean
    public SecurityManager getSecurityManager(){
        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
        defaultSecurityManager.setRealm(getJwtRealm());
        // 关闭 ShiroDAO 功能,不需要将 Shiro Session 中的东西存到任何地方（包括 Http Session 中）
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        defaultSecurityManager.setSubjectDAO(subjectDAO);
        //禁止Subject的getSession方法
        defaultSecurityManager.setSubjectFactory(subjectFactory());

        return  defaultSecurityManager;
    }

    /*
    * @Description: 过滤，跳转设置
    * @Author: LZY
    * @Date: 2021/4/13 19:47
    * @Params:
    * @Return:
    */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/user/login");
        shiroFilterFactoryBean.setSuccessUrl("/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/error/unauthorized");
        /*
         * 添加jwt过滤器，并在下面注册,也就是将jwtFilter注册到shiro的Filter中
         * */
        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put("anon", new MyAnonymousFilter());
        filterMap.put("jwt", new JwtFilter());
        shiroFilterFactoryBean.setFilters(filterMap);

        Map<String, String> filterChainMap = new LinkedHashMap<>();
        // 配置无需权限认证的url
        filterChainMap.put("/user/login", "anon");
        filterChainMap.put("/user/register", "anon");
        filterChainMap.put("/user/searchbyphone","anon");
        filterChainMap.put("/user/phonecode", "anon");
        filterChainMap.put("/user/emailcode", "anon");
        filterChainMap.put("/user/password/forget", "anon");
        filterChainMap.put("/user/searchbyphone","anon");
        filterChainMap.put("/parking/entrance/plate/receiver", "anon");
        filterChainMap.put("/parking/exit/plate/receiver", "anon");
        // swagger-ui
        filterChainMap.put("/swagger-ui.html", "anon");
        filterChainMap.put("/swagger-resources", "anon");
        filterChainMap.put("/swagger-resources/configuration/security", "anon");
        filterChainMap.put("/swagger-resources/configuration/ui", "anon");
        filterChainMap.put("/v2/api-docs", "anon");
        filterChainMap.put("/webjars/springfox-swagger-ui/**", "anon");
        // 指定除了anon之外的请求都先经过jwtFilter
        filterChainMap.put("/**", "jwt");
//        filterChainMap.put("/**", "anon");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        return shiroFilterFactoryBean;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /*
    * @Description:  开启Shiro的注解(如@RequiresRoles,@RequiresPermissions)
    * @Author: LZY
    * @Date: 2021/4/13 19:58
    * @Params:
    * @Return:
    */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(getSecurityManager());
        return authorizationAttributeSourceAdvisor;
    }
}
